package cn.xy.base.server.controller.admapi;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.RandomUtil;
import cn.xy.base.server.bean.IPage;
import cn.xy.base.server.dto.PasswordUpdateDTO;
import cn.xy.base.server.dto.ResetPasswordDTO;
import cn.xy.base.server.dto.SysAdminAddDTO;
import cn.xy.base.server.dto.SysAdminUpdateDTO;
import cn.xy.base.server.dto.SysUpdateAccountDTO;
import cn.xy.base.server.enums.RoleEnum;
import cn.xy.base.server.po.SysAdmin;
import cn.xy.base.server.po.SysPermission;
import cn.xy.base.server.po.SysRole;
import cn.xy.base.server.service.SysAdminService;
import cn.xy.base.server.service.SysPermissionService;
import cn.xy.base.server.service.SysRoleService;
import cn.xy.base.server.vo.SysAdminListVO;
import cn.xy.base.server.vo.SysAdminSimpleListVO;
import cn.xy.base.server.vo.SysAdminVO;
import cn.xy.base.server.vo.SysRoleVO;
import cn.xy.base.server.web.AdminWebContext;
import cn.xy.commons.annotation.OperateLog;
import cn.xy.commons.annotation.RepeatSubmit;
import cn.xy.commons.constant.Consts;
import cn.xy.commons.core.Result;
import cn.xy.commons.enums.DisableStatus;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 表[sys_admin]对应的后台管理类
 *
 * @author auto
 */

@Slf4j
@RestController
@RequestMapping("/admapi/sys/admin")
@Api(tags = {"管理员管理接口"})
public class SysAdminAdminController {

    @Autowired
    private SysAdminService sysAdminService;

    @Autowired
    private SysRoleService sysRoleService;

    @Autowired
    private SysPermissionService sysPermissionService;

    @ApiOperation(value = "管理员管理员-列表")
    @GetMapping("/list")
    @PreAuthorize("@validate.hasPermission('system-user-list')")
    public Result<Page<SysAdminListVO>> adminList(@RequestParam(required = false, defaultValue = "") String username,
                                                  @RequestParam(required = false, defaultValue = "0") int status,
                                                  IPage page) {
        LambdaQueryWrapper<SysAdmin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(CharSequenceUtil.isNotEmpty(username), SysAdmin::getUsername, username);
        queryWrapper.eq(status > 0, SysAdmin::getStatus, status);
        Page<SysAdmin> pageData = sysAdminService.page(page.toPage(), queryWrapper);
        List<SysAdminListVO> sysAdminVOList = pageData.getRecords().stream().map(SysAdminListVO::new).collect(Collectors.toList());
        Page<SysAdminListVO> result = new Page<>();
        result.setTotal(pageData.getTotal());
        result.setRecords(sysAdminVOList);
        result.setCurrent(page.getCurrent());
        result.setSize(page.getSize());
        return Result.data(result);
    }

    @ApiOperation(value = "管理员管理员-列表(无分页)")
    @GetMapping("/listJson")
    public Result<List<SysAdminSimpleListVO>> listJson() {
        LambdaQueryWrapper<SysAdmin> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysAdmin::getStatus, DisableStatus.NORMAL.getValue());
        List<SysAdmin> adminList = sysAdminService.list(queryWrapper);
        List<SysAdminSimpleListVO> sysAdminVOList = adminList.stream().map(SysAdminSimpleListVO::new).collect(Collectors.toList());
        return Result.data(sysAdminVOList);
    }

    @ApiOperation(value = "管理员管理员-登陆用户详情")
    @GetMapping("/info")
    public Result<SysAdminVO> info() {
        int adminId = AdminWebContext.getAdminId();
        SysAdmin sysAdmin = sysAdminService.getById(adminId);
        if (sysAdmin == null) {
            return Result.error("账户不存在");
        }

        List<SysPermission> permissionList = new ArrayList<>();
        SysRoleVO roleVO = null;
        if (sysAdmin.getRoleId() > 0) {
            SysRole role = sysRoleService.getById(sysAdmin.getRoleId());
            if (role != null) {
                roleVO = new SysRoleVO(role);
                List<Long> permissionIdList = Arrays.stream(role.getPermissions().split(Consts.COMMA)).map
                        (Long::parseLong).collect(Collectors.toList());
                permissionList = sysPermissionService.getPermissionListByIdIn(permissionIdList);
            }
        }

        SysAdminVO sysAdminVO = new SysAdminVO(sysAdmin);
        sysAdminVO.setPermissionList(sysPermissionService.generateTree(permissionList));
        sysAdminVO.setRole(roleVO);
        return Result.data(sysAdminVO);
    }

    @ApiOperation(value = "管理员-详情")
    @GetMapping("/detail")
    @PreAuthorize("@validate.hasPermission('system-user-detail')")
    public Result<SysAdminVO> detail(int id) {
        SysAdmin sysAdmin = sysAdminService.getById(id);
        if (sysAdmin == null) {
            return Result.error("账户不存在");
        }

        List<SysPermission> permissionList = new ArrayList<>();
        SysRoleVO roleVO = null;
        if (sysAdmin.getRoleId() > 0) {
            SysRole role = sysRoleService.getById(sysAdmin.getRoleId());
            if (role != null) {
                roleVO = new SysRoleVO(role);
                List<Long> permissionIdList = Arrays.stream(role.getPermissions().split(Consts.COMMA)).map
                        (Long::parseLong).collect(Collectors.toList());
                permissionList = sysPermissionService.getPermissionListByIdIn(permissionIdList);
            }
        }

        SysAdminVO sysAdminVO = new SysAdminVO(sysAdmin);
        sysAdminVO.setPermissionList(sysPermissionService.generateTree(permissionList));
        sysAdminVO.setRole(roleVO);
        return Result.data(sysAdminVO);
    }

    @ApiOperation(value = "增加管理员账号")
    @PostMapping("/add")
    @OperateLog(description = "增加管理员账号")
    @PreAuthorize("@validate.hasPermission('system-user-add')")
    @RepeatSubmit
    public Result<String> add(@Validated @RequestBody SysAdminAddDTO sysAdminAddDTO) {
        if (!RoleEnum.isSuperAdmin(AdminWebContext.getRoleId()) && RoleEnum.isSuperAdmin(sysAdminAddDTO.getRoleId())) {
            return Result.error("只有超级管理员才能新建超级管理员账号");
        }
        SysAdmin sysAdmin = sysAdminService.getByUsername(sysAdminAddDTO.getUsername());
        if (sysAdmin != null) {
            return Result.error("该管理员名已被注册");
        }
        sysAdmin = sysAdminAddDTO.toSysAdmin();
        String salt = RandomUtil.randomString(16);
        String password = sysAdminService.encodePassword(sysAdminAddDTO.getPassword(), salt);
        sysAdmin.setSalt(salt);
        sysAdmin.setPassword(password);
        sysAdmin.setStatus(DisableStatus.NORMAL.getValue());
        sysAdminService.save(sysAdmin);
        return Result.ok("添加成功");
    }

    @ApiOperation(value = "更改管理员账号信息")
    @PostMapping("/update")
    @OperateLog(description = "更改管理员账号信息")
    @PreAuthorize("@validate.hasPermission('system-user-update')")
    @RepeatSubmit
    public Result<String> update(@Validated @RequestBody SysAdminUpdateDTO sysAdminUpdateDTO) {
        SysAdmin sysAdmin = sysAdminService.getById(sysAdminUpdateDTO.getId());
        if (sysAdmin == null) {
            return Result.error(SysAdminService.SYS_ADMIN_NOT_EXIST);
        }
        if (!RoleEnum.isSuperAdmin(AdminWebContext.getRoleId()) && RoleEnum.isSuperAdmin(sysAdmin.getRoleId())) {
            return Result.error("只有超级管理员才能更改超级管理员的账号");
        }
        SysAdmin username = sysAdminService.getByUsername(sysAdminUpdateDTO.getUsername());
        if (username != null && !Objects.equals(username.getId(), sysAdmin.getId())) {
            return Result.error("该账号已被使用");
        }
        BeanUtil.copyProperties(sysAdminUpdateDTO, sysAdmin, "password");
        if (CharSequenceUtil.isNotEmpty(sysAdminUpdateDTO.getPassword())) {
            String password = sysAdmin.getPassword();
            String salt = sysAdmin.getSalt();
            if (CharSequenceUtil.isNotEmpty(sysAdminUpdateDTO.getPassword())) {
                salt = RandomUtil.randomString(16);
                password = sysAdminService.encodePassword(sysAdminUpdateDTO.getPassword(), salt);
            }
            sysAdmin.setPassword(password);
            sysAdmin.setSalt(salt);
        }
        sysAdminService.updateById(sysAdmin);
        return Result.ok("修改成功");
    }

    @ApiOperation(value = "更改登录账号信息")
    @PostMapping("/updateAccount")
    @OperateLog(description = "更改登录账号信息")
    public Result<String> update(@Validated @RequestBody SysUpdateAccountDTO dto) {
        SysAdmin sysAdmin = sysAdminService.getById(AdminWebContext.getAdminId());
        if (sysAdmin == null) {
            return Result.error(SysAdminService.SYS_ADMIN_NOT_EXIST);
        }
        BeanUtil.copyProperties(dto, sysAdmin, "password");
        if (CharSequenceUtil.isNotEmpty(dto.getPassword())) {
            String password = sysAdmin.getPassword();
            String salt = sysAdmin.getSalt();
            if (CharSequenceUtil.isNotEmpty(dto.getPassword())) {
                salt = RandomUtil.randomString(16);
                password = sysAdminService.encodePassword(dto.getPassword(), salt);
            }
            sysAdmin.setPassword(password);
            sysAdmin.setSalt(salt);
        }
        sysAdminService.updateById(sysAdmin);
        return Result.ok("修改成功");
    }

    @ApiOperation(value = "管理员-禁用启动")
    @PostMapping("/disable")
    @OperateLog(description = "管理员-禁用启动")
    @PreAuthorize("@validate.hasPermission('system-user-disable')")
    @RepeatSubmit
    public Result<String> disable(int id) {
        if (id == AdminWebContext.getAdminId()) {
            return Result.error("你无法禁用自己的账号");
        }
        SysAdmin sysAdmin = sysAdminService.getById(id);
        if (sysAdmin == null) {
            return Result.error(SysAdminService.SYS_ADMIN_NOT_EXIST);
        }
        if (!RoleEnum.isSuperAdmin(AdminWebContext.getRoleId()) && RoleEnum.isSuperAdmin(sysAdmin.getRoleId())) {
            return Result.error("只有超级管理员才能更改超级管理员的账号");
        }
        sysAdmin.setStatus(DisableStatus.negate(sysAdmin.getStatus()));
        sysAdminService.updateById(sysAdmin);
        return Result.ok("编辑成功");
    }

    @ApiOperation(value = "通过旧密码修改密码")
    @PostMapping("/updatePwdByOldPwd")
    @OperateLog(description = "通过旧密码修改密码")
    @PreAuthorize("@validate.hasPermission('system-user-update-password')")
    @RepeatSubmit
    public Result<String> updatePwdByOldPwd(@Validated @RequestBody PasswordUpdateDTO passwordUpdateDTO) {
        SysAdmin sysAdmin = sysAdminService.getById(AdminWebContext.getAdminId());
        if (sysAdmin == null) {
            return Result.error(SysAdminService.SYS_ADMIN_NOT_EXIST);
        }
        String oldPassword = sysAdminService.encodePassword(passwordUpdateDTO.getOldPassword(), sysAdmin.getSalt());
        if (!sysAdmin.getPassword().equals(oldPassword)) {
            return Result.error("旧密码错误");
        }
        String salt = RandomUtil.randomString(16);
        String password = sysAdminService.encodePassword(passwordUpdateDTO.getPassword(), salt);
        sysAdmin.setSalt(salt);
        sysAdmin.setPassword(password);
        sysAdminService.updateById(sysAdmin);
        return Result.ok("修改成功");
    }

    @ApiOperation(value = "管理员-重置密码")
    @PostMapping("/resetPassword")
    @OperateLog(description = "重置密码")
    @PreAuthorize("@validate.hasPermission('system-user-reset-password')")
    @RepeatSubmit
    public Result<String> resetPassword(@Validated @RequestBody ResetPasswordDTO resetPasswordDTO) {
        SysAdmin sysAdmin = sysAdminService.getById(resetPasswordDTO.getId());
        if (sysAdmin == null) {
            return Result.error(SysAdminService.SYS_ADMIN_NOT_EXIST);
        }
        String salt = RandomUtil.randomString(16);
        String password = sysAdminService.encodePassword(resetPasswordDTO.getPassword(), salt);
        sysAdmin.setSalt(salt);
        sysAdmin.setPassword(password);
        sysAdminService.updateById(sysAdmin);
        return Result.ok("修改成功");
    }

}
